package com.csust.automaticteach.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.csust.automaticteach.app.common.ExerciseEvaluateApp;
import com.csust.automaticteach.exception.BusinessException;
import com.csust.automaticteach.exception.ErrorCode;
import com.csust.automaticteach.exception.ThrowUtils;
import com.csust.automaticteach.model.dto.exercisessubmit.JudgeExercisesRequest;
import com.csust.automaticteach.model.dto.exercisessubmit.JudgeExercisesRequestForAI;
import com.csust.automaticteach.model.entity.ExercisesSubmit;
import com.csust.automaticteach.model.entity.User;
import com.csust.automaticteach.model.enums.ExercisesSubmitStatusEnum;
import com.csust.automaticteach.model.vo.exercises.ExercisesVO;
import com.csust.automaticteach.model.vo.exercisessubmit.ExercisesSubmitVO;
import com.csust.automaticteach.service.ExercisesSetsService;
import com.csust.automaticteach.service.ExercisesSubmitService;
import com.csust.automaticteach.mapper.ExercisesSubmitMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import static cn.hutool.json.JSONUtil.toJsonPrettyStr;
import static cn.hutool.json.JSONUtil.toJsonStr;

/**
* @author 钰玟
* @description 针对表【t_exercises_submit(练习提交表)】的数据库操作Service实现
* @createDate 2025-08-20 17:50:56
*/
@Service
public class ExercisesSubmitServiceImpl extends ServiceImpl<ExercisesSubmitMapper, ExercisesSubmit>
    implements ExercisesSubmitService{
    @Resource
    private ExercisesSetsService exercisesSetsService;
    @Resource
    private ExerciseEvaluateApp exerciseEvaluateApp;
    /**
     * 判题
     * @param judgeExercisesRequest 判题请求
     * @return 判题结果
     */
    @Override
    public List<ExerciseEvaluateApp.judgeResponse> judgeExercises(JudgeExercisesRequest judgeExercisesRequest,User loginUser) {
        // 1. 提取 相关参数
        Long setId = judgeExercisesRequest.getId();
        HashMap<Long, String> userAns = judgeExercisesRequest.getUserAns();
        //2. 获取题目相关信息
        List<ExercisesVO> exerciseVOList = exercisesSetsService.getExerciseVOList(setId);
        // 准备插入 submit的信息
        List<ExercisesSubmit> exercisesSubmitList = new ArrayList<>();
        //3.构造submitList并构造判题请求
        List<JudgeExercisesRequestForAI> requestForAIList = exerciseVOList.stream().map(exercisesVO -> {
            String uAns = userAns.get(exercisesVO.getId());
            //3.1获取到 exerciseId 以及 userAns 即可
            ExercisesSubmit exercisesSubmit = new ExercisesSubmit();
            exercisesSubmit.setExercisesId(exercisesVO.getId());
            exercisesSubmit.setStatus(ExercisesSubmitStatusEnum.WAITING.getValue());
            exercisesSubmit.setAnswer(uAns);
            exercisesSubmit.setUserId(loginUser.getId());
            exercisesSubmitList.add(exercisesSubmit);
            //3.2 构造判题请求
            JudgeExercisesRequestForAI judgeExercisesRequestForAI = new JudgeExercisesRequestForAI();
            BeanUtil.copyProperties(exercisesVO, judgeExercisesRequestForAI);
            judgeExercisesRequestForAI.setUserAns(uAns);
            //返回判题请求
            return judgeExercisesRequestForAI;
        }).toList();
        //4. 插入数据库
        Thread.ofVirtual().start(() -> {
            // 虚拟线程批量插入数据库
            this.saveBatch(exercisesSubmitList);
        });
        // 格式化的json字符串
        String requestForAIListStr = toJsonPrettyStr(requestForAIList);
//        String requestForAIListStr = toJsonStr(requestForAIList);
        //5. 调用判题服务
        String chatId = UUID.randomUUID().toString();
        List<ExerciseEvaluateApp.judgeResponse> judgeResponseList = exerciseEvaluateApp.doEvaluate(requestForAIListStr, chatId);
        return judgeResponseList;
    }

    @Override
    public Flux<String> judgeExercisesByStream(JudgeExercisesRequest judgeExercisesRequest,User loginUser) {
        // 1. 提取 相关参数
        Long setId = judgeExercisesRequest.getId();
        HashMap<Long, String> userAns = judgeExercisesRequest.getUserAns();
        //2. 获取题目相关信息
        List<ExercisesVO> exerciseVOList = exercisesSetsService.getExerciseVOList(setId);
        // 准备插入 submit的信息
        List<ExercisesSubmit> exercisesSubmitList = new ArrayList<>();
        //3.构造submitList并构造判题请求
        List<JudgeExercisesRequestForAI> requestForAIList = exerciseVOList.stream().map(exercisesVO -> {
            String uAns = userAns.get(exercisesVO.getId());
            //3.1获取到 exerciseId 以及 userAns 即可
            ExercisesSubmit exercisesSubmit = new ExercisesSubmit();
            exercisesSubmit.setExercisesId(exercisesVO.getId());
            exercisesSubmit.setStatus(ExercisesSubmitStatusEnum.WAITING.getValue());
            exercisesSubmit.setAnswer(uAns);
            exercisesSubmit.setUserId(loginUser.getId());
            exercisesSubmitList.add(exercisesSubmit);
            //3.2 构造判题请求
            JudgeExercisesRequestForAI judgeExercisesRequestForAI = new JudgeExercisesRequestForAI();
            BeanUtil.copyProperties(exercisesVO, judgeExercisesRequestForAI);
            judgeExercisesRequestForAI.setUserAns(uAns);
            //返回判题请求
            return judgeExercisesRequestForAI;
        }).toList();
        //4. 插入数据库
        Thread.ofVirtual().start(() -> {
            //5. 批量插入数据库
            this.saveBatch(exercisesSubmitList);
        });
        //5. 调用判题服务 并返回结果
        String requestForAIListStr = toJsonStr(requestForAIList);
        String chatId = UUID.randomUUID().toString();
        return exerciseEvaluateApp.doEvaluateByStream(requestForAIListStr, chatId);
    }

    @Override
    public void updateSubmitResult(ExerciseEvaluateApp.judgeResponse judgeResponse) {
        //1.根据 exerciseId 查询submit 记录
        QueryWrapper<ExercisesSubmit> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("exercisesId", judgeResponse.id())
                .orderByDesc("createTime")  // 按 createTime 降序排序
                .last("LIMIT 1");          // 取第一条记录
        ExercisesSubmit exercisesSubmit = this.getOne(queryWrapper);
        if (exercisesSubmit == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"判题失败");
        }
        BeanUtil.copyProperties(judgeResponse, exercisesSubmit, "id");
        Integer toSetStatus = judgeResponse.isCorrect() ? ExercisesSubmitStatusEnum.RIGHT.getValue() :ExercisesSubmitStatusEnum.WRONG.getValue();
        exercisesSubmit.setStatus(toSetStatus);
        exercisesSubmit.setImprovement(judgeResponse.improvement());
        boolean saved = this.saveOrUpdate(exercisesSubmit);
        ThrowUtils.throwIf(!saved, ErrorCode.OPERATION_ERROR);
    }
}




